#include "i2c_user.h"

i2c_handle_type hi2c1;
i2c_handle_type hi2c2;

/**
  * @brief  initializes peripherals used by the i2c.
  * @param  none
  * @retval none
  */
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
  gpio_init_type gpio_initstructure;

  if(hi2c->i2cx == I2C1_PORT)
  {
    /* i2c periph clock enable */
    crm_periph_clock_enable(I2C1_CLK, TRUE);
    crm_periph_clock_enable(I2C1_SCL_GPIO_CLK, TRUE);
    crm_periph_clock_enable(I2C1_SDA_GPIO_CLK, TRUE);

    /* gpio configuration */
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

    /* configure i2c pins: scl */
    gpio_initstructure.gpio_pins = I2C1_SCL_PIN;
    gpio_init(I2C1_SCL_GPIO_PORT, &gpio_initstructure);

    /* configure i2c pins: sda */
    gpio_initstructure.gpio_pins = I2C1_SDA_PIN;
    gpio_init(I2C1_SDA_GPIO_PORT, &gpio_initstructure);

    /* configure and enable i2c dma channel interrupt */
    nvic_irq_enable(I2C1_DMA_TX_IRQn, 0, 0);
    nvic_irq_enable(I2C1_DMA_RX_IRQn, 0, 0);

    /* configure and enable i2c interrupt */
    nvic_irq_enable(I2C1_EVT_IRQn, 0, 0);
    nvic_irq_enable(I2C1_ERR_IRQn, 0, 0);

    /* i2c dma tx and rx channels configuration */
    /* enable the dma clock */
    crm_periph_clock_enable(I2C1_DMA_CLK, TRUE);

    /* i2c dma channel configuration */
    dma_reset(hi2c->dma_tx_channel);
    dma_reset(hi2c->dma_rx_channel);

    hi2c->dma_tx_channel = I2C1_DMA_TX_CHANNEL;
    hi2c->dma_rx_channel = I2C1_DMA_RX_CHANNEL;

    dma_default_para_init(&hi2c->dma_init_struct);
    hi2c->dma_init_struct.peripheral_inc_enable    = FALSE;
    hi2c->dma_init_struct.memory_inc_enable        = TRUE;
    hi2c->dma_init_struct.peripheral_data_width    = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    hi2c->dma_init_struct.memory_data_width        = DMA_MEMORY_DATA_WIDTH_BYTE;
    hi2c->dma_init_struct.loop_mode_enable         = FALSE;
    hi2c->dma_init_struct.priority                 = DMA_PRIORITY_LOW;
    hi2c->dma_init_struct.direction                = DMA_DIR_MEMORY_TO_PERIPHERAL;

    dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);
    dma_init(hi2c->dma_rx_channel, &hi2c->dma_init_struct);
    
    dma_flexible_config(DMA1, FLEX_CHANNEL6, DMA_FLEXIBLE_I2C1_TX);
    dma_flexible_config(DMA1, FLEX_CHANNEL7, DMA_FLEXIBLE_I2C1_RX);

    i2c_init(hi2c->i2cx, I2C_FSMODE_DUTY_2_1, I2C1_SPEED);

    i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2C1_ADDRESS);
  }
  else if(hi2c->i2cx == I2C2_PORT)
  {
    /* i2c periph clock enable */
    crm_periph_clock_enable(I2C2_CLK, TRUE);
    crm_periph_clock_enable(I2C2_SCL_GPIO_CLK, TRUE);
    crm_periph_clock_enable(I2C2_SDA_GPIO_CLK, TRUE);

    /* gpio configuration */
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

    gpio_pin_remap_config(I2C2_GMUX_0001, TRUE);
    
    /* configure i2c pins: scl */
    gpio_initstructure.gpio_pins = I2C2_SCL_PIN;
    gpio_init(I2C2_SCL_GPIO_PORT, &gpio_initstructure);

    /* configure i2c pins: sda */
    gpio_initstructure.gpio_pins = I2C2_SDA_PIN;
    gpio_init(I2C2_SDA_GPIO_PORT, &gpio_initstructure);

    /* configure and enable i2c dma channel interrupt */
    nvic_irq_enable(I2C2_DMA_TX_IRQn, 0, 0);
    nvic_irq_enable(I2C2_DMA_RX_IRQn, 0, 0);

    /* configure and enable i2c interrupt */
    nvic_irq_enable(I2C2_EVT_IRQn, 0, 0);
    nvic_irq_enable(I2C2_ERR_IRQn, 0, 0);

    /* i2c dma tx and rx channels configuration */
    /* enable the dma clock */
    crm_periph_clock_enable(I2C2_DMA_CLK, TRUE);

    /* i2c dma channel configuration */
    dma_reset(hi2c->dma_tx_channel);
    dma_reset(hi2c->dma_rx_channel);

    hi2c->dma_tx_channel = I2C2_DMA_TX_CHANNEL;
    hi2c->dma_rx_channel = I2C2_DMA_RX_CHANNEL;

    dma_default_para_init(&hi2c->dma_init_struct);
    hi2c->dma_init_struct.peripheral_inc_enable    = FALSE;
    hi2c->dma_init_struct.memory_inc_enable        = TRUE;
    hi2c->dma_init_struct.peripheral_data_width    = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    hi2c->dma_init_struct.memory_data_width        = DMA_MEMORY_DATA_WIDTH_BYTE;
    hi2c->dma_init_struct.loop_mode_enable         = FALSE;
    hi2c->dma_init_struct.priority                 = DMA_PRIORITY_LOW;
    hi2c->dma_init_struct.direction                = DMA_DIR_MEMORY_TO_PERIPHERAL;

    dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);
    dma_init(hi2c->dma_rx_channel, &hi2c->dma_init_struct);

    dma_flexible_config(DMA1, FLEX_CHANNEL4, DMA_FLEXIBLE_I2C2_TX);
    dma_flexible_config(DMA1, FLEX_CHANNEL5, DMA_FLEXIBLE_I2C2_RX);

    i2c_init(hi2c->i2cx, I2C_FSMODE_DUTY_2_1, I2C2_SPEED);

    i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2C2_ADDRESS);
  }
}

void i2c_user_init(void)
{
  hi2c1.i2cx = I2C1_PORT;
  i2c_config(&hi2c1);
}

void i2c2_user_init(void)
{
  hi2c2.i2cx = I2C2_PORT;
  i2c_config(&hi2c2);
}